package mc0101.mccache.util;

import lombok.extern.slf4j.Slf4j;
import mc0101.mccache.cache.TwoLevelLocalCache;
import mc0101.mccache.entity.ComParmInf;
import mc0101.mccache.holder.ZcCacheApplicationContextHolder;
import mc0101.mccache.repository.ZcCacheRepository;
import mc0101.mccache.thread.LocalAndRemoteRefreshThread;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Slf4j
public final class RemcParmCache {


    /**
     * 获取当前类型的所有参数
     *
     * @param paramClass 参数类类型
     * @param <T>        参数类
     * @return 参数集合
     */
    public static <T> List<T> getParamList(Class<T> paramClass) {
        return getParamList(paramClass, null);
    }

    /**
     * 根据参数类型获取通用参数的参数列表，如果parmTyp为空，则返回null
     * @param paramTyp 通用参数参数类型
     * @return
     */
    public static List<ComParmInf> getComParmListByParmTyp(String paramTyp){
        Map<String, Object> filters = new HashMap<>();
        filters.put("parmTyp", paramTyp);

        return getParamList(ComParmInf.class, filters);
    }

    /**
     * 根据参数类型获取通用参数的参数列表，如果parmTyp为空，则返回null
     * @param paramTyp 通用参数参数类型
     * @return
     */
    public static ComParmInf getComParmObjectByParmTypAndKey(String paramTyp, String paramKey){
        Map<String, Object> filters = new HashMap<>();
        filters.put("parmTyp", paramTyp);
        filters.put("parmKey", paramKey);

        return getParamObject(ComParmInf.class, filters);
    }

    /**
     * 根据参数类型获取通用参数的参数列表，如果parmTyp为空，则返回null
     * @param paramTyp 通用参数参数类型
     * @return
     */
    public static ComParmInf getValidComParmObjectByParmTypAndKey(String paramTyp, String paramKey){
        Map<String, Object> filters = new HashMap<>();
        filters.put("parmTyp", paramTyp);
        filters.put("parmKey", paramKey);
        filters.put("effFlg", "1");
        return getParamObject(ComParmInf.class, filters);
    }

    /**
     * 根据条件返回单个对象
     * @param paramClass 参数类类型
     * @param filters 过滤条件
     * @param <T> 参数类
     * @return 返回单个对象
     */
    public static <T> T getParamObject(Class<T> paramClass, Map<String, Object> filters){
        List<T> list = getParamList(paramClass, filters);
        if (null != list && list.size() > 0){
            return list.get(0);
        }
        return null;
    }

    /**
     * 根据条件返回单个对象
     * @param paramClass 参数类类型
     * @param <T> 参数类
     * @param filterName 过滤栏位名称
     * @param filterValue 过滤栏位值
     * @return 返回单个对象
     */
    public static <T> T getParamObject(Class<T> paramClass, String filterName, String filterValue){
        Map<String, Object> filters = new HashMap<>();
        filters.put(filterName, filterValue);
        List<T> list = getParamList(paramClass, filters);
        if (null != list && list.size() > 0){
            return list.get(0);
        }
        return null;
    }

    /**
     * 根据条件返回单个生效对象
     * @param paramClass 参数类类型
     * @param <T> 参数类
     * @param paramClass 参数类类型
     * @param filterName 过滤栏位名称
     * @return 返回单个对象
     */
    public static <T> T getValidParamObject(Class<T> paramClass, String filterName, String filterValue){
        Map<String, Object> filters = new HashMap<>();
        filters.put(filterName, filterValue);
        filters.put("effFlg", "1");

        List<T> list = getParamList(paramClass, filters);
        if (null != list && list.size() > 0){
            return list.get(0);
        }
        return null;
    }

    /**
     * 返回有效参数
     * @param paramClass 参数类类型
     * @param <T> 参数类
     * @param paramClass 参数类类型
     * @param filterName 过滤栏位名称
     * @return 返回单个对象
     */
    public static <T> List<T> getParamList(Class<T> paramClass, String filterName, String filterValue) {
        Map<String, Object> filters = new HashMap<>();
        filters.put(filterName, filterValue);
        return getParamList(paramClass, filters);
    }

    /**
     * 返回有效参数
     * @param paramClass 参数类类型
     * @param <T> 参数类
     * @param paramClass 参数类类型
     * @param filterName 过滤栏位名称
     * @return 返回单个对象
     */
    public static <T> List<T> getValidParamList(Class<T> paramClass, String filterName, String filterValue) {
        Map<String, Object> filters = new HashMap<>();
        filters.put(filterName, filterValue);
        filters.put("effFlg", "1");
        return getParamList(paramClass, filters);
    }

    /**
     * 返回有效参数
     * @param paramClass 参数类类型
     * @param <T> 参数类
     * @return 返回单个对象
     */
    public static <T> List<T> getValidParamList(Class<T> paramClass) {
        Map<String, Object> filters = new HashMap<>();
        filters.put("effFlg", "1");
        return getParamList(paramClass, filters);
    }

    /**
     * 返回有效参数
     * @param paramClass 参数类类型
     * @param <T> 参数类
     * @return 返回单个对象
     */
    public static <T> List<T> getValidParamList(Class<T> paramClass, Map<String, Object> filters) {
        if (filters == null || filters.isEmpty()){
            return getValidParamList(paramClass);
        }
        filters.put("effFlg", "1");
        return getParamList(paramClass, filters);
    }

    /**
     * 返回有效参数
     * @param paramClass 参数类类型
     * @param <T> 参数类
     * @return 返回单个对象
     */
    public static <T> T getValidParamObject(Class<T> paramClass) {
        Map<String, Object> filters = new HashMap<>();
        filters.put("effFlg", "1");
        return getParamObject(paramClass, filters);
    }

    /**
     * 返回有效参数
     * @param paramClass 参数类类型
     * @param <T> 参数类
     * @return 返回单个对象
     */
    public static <T> T getValidParamObject(Class<T> paramClass, Map<String, Object> filters) {
        if (filters == null || filters.isEmpty()){
            return getValidParamObject(paramClass);
        }
        filters.put("effFlg", "1");
        return getParamObject(paramClass, filters);
    }

    /**
     * 传入一个过滤键值过滤值，返回参数列表
     * @param paramClass 参数类类型
     * @param <T> 参数类
     * @return 返回单个对象
     */
    public static <T> List<T> getFilterParamList(Class<T> paramClass, String filterKey, Object filterObject) {
        if (StringUtils.isEmpty(filterKey)){
            log.warn("想要根据filterKey获取参数列表，但传入的filterKey为空，请确认是否合适！");
            return getParamList(paramClass);
        }
        Map<String, Object> filters = new HashMap<>();
        filters.put(filterKey, filterObject);
        return getParamList(paramClass, filters);
    }

    /**
     * 传入一个过滤键值过滤值，返回有效参数列表
     * @param paramClass 参数类类型
     * @param <T> 参数类
     * @return 返回单个对象
     */
    public static <T> List<T> getValidAndFilterParamList(Class<T> paramClass, String filterKey, Object filterObject) {
        if (StringUtils.isEmpty(filterKey)){
            log.warn("想要根据filterKey获取有效参数列表，但传入的filterKey为空，请确认是否合适！");
            return getValidParamList(paramClass);
        }
        Map<String, Object> filters = new HashMap<>();
        filters.put("effFlg", "1");
        filters.put(filterKey, filterObject);
        return getParamList(paramClass, filters);
    }

    /**
     * 传入一个过滤键值过滤值，返回参数对象
     * @param paramClass 参数类类型
     * @param <T> 参数类
     * @return 返回单个对象
     */
    public static <T> T getFilterParamObject(Class<T> paramClass, String filterKey, Object filterObject) {
        if (StringUtils.isEmpty(filterKey)){
            log.warn("想要根据filterKey获取参数对象，但传入的filterKey为空，请确认是否合适！");
            return null;
        }
        Map<String, Object> filters = new HashMap<>();
        filters.put(filterKey, filterObject);
        return getParamObject(paramClass, filters);
    }

    /**
     * 传入一个过滤键值过滤值，返回参数对象
     * @param paramClass 参数类类型
     * @param <T> 参数类
     * @return 返回单个对象
     */
    public static <T> T getValidAndFilterParamObject(Class<T> paramClass, String filterKey, Object filterObject) {
        if (StringUtils.isEmpty(filterKey)){
            log.warn("想要根据filterKey获取有效参数对象，但传入的filterKey为空，请确认是否合适！");
            return getValidParamObject(paramClass);
        }
        Map<String, Object> filters = new HashMap<>();
        filters.put(filterKey, filterObject);
        return getValidParamObject(paramClass, filters);
    }

    /**
     * 根据过滤条件，查询所需参数
     *
     * @param paramClass 参数类类型
     * @param filters     过滤条件
     * @param <T>        参数类
     * @return 查询过滤所得参数
     */
    public static <T> List<T> getParamList(Class<T> paramClass, Map<String, Object> filters) {
        long begin = System.currentTimeMillis();
        // 获取参数类名
        String paramClassName = getClassName(paramClass);

        // 使用二级缓存，这一块要加开关
        String twoLevelCacheKey = paramClass.getTypeName() + ((filters == null || filters.size() == 0) ? "{}" : filters.toString());

        Object cacheByKey = CacheBean.twoLevelLocalCache.getCacheByKey(twoLevelCacheKey, CacheBean.refreshThread);
        if (cacheByKey != null){
            return (List<T>) cacheByKey;
        }

        // 获取缓存中的所有参数
        List<Map<String, Object>> paramMapList = CacheBean.zcCacheRepository.getParamByParamClassName(paramClassName
                , CacheBean.refreshThread);
        if(null == paramMapList){
            log.warn("RemcParmCache没有查询到参数类型【"+paramClass.getName()+":"+paramClassName+"】，请检查参数类型" +
                    "是否正确，系统参数名是否正确以及版本规则参数是否配置！");
            return null;
        }

        // 根据条件过滤参数
        long begin1 = System.currentTimeMillis();
        if (null != filters && filters.size() > 0) {
            paramMapList = filterParamList(filters, paramMapList);
        }
        log.debug("类名："+paramClassName+"过滤参数消耗时间为：" + (System.currentTimeMillis() - begin1) + "ms");

        // 返回转换后的类
        List<T> result = ConvertUtils.convertBeanList(paramClass, paramMapList);

        // 二级缓存打开时，要缓存每一次的查询结果
        CacheBean.twoLevelLocalCache.putCache(twoLevelCacheKey, result);

        log.debug("类名："+paramClassName+"查询缓存消耗总时间为：" + (System.currentTimeMillis() - begin) + "ms");
        return result;
    }

    /**
     * 获取类的类名
     * @param paramClass 类
     * @param <T> 类型
     * @return 类名
     */
    private static <T> String getClassName(Class<T> paramClass) {
        String name = paramClass.getName();
        String[] names = name.split("\\.");
        int length = names.length;
        return names[length - 1];
    }

    /**
     * 根据条件，过滤参数集合
     * @param filters 条件
     * @param paramMapList 参数集合
     * @return 过滤后的集合
     */
    private static List<Map<String, Object>> filterParamList(Map<String, Object> filters, List<Map<String, Object>> paramMapList) {
        List<Map<String, Object>> filterMapList = new ArrayList<Map<String, Object>>();
        for (Map<String, Object> item : paramMapList) {
            boolean isFilter = false; // 默认不被过滤
            for (Map.Entry<String, Object> entry : filters.entrySet()) {

                // 不包含这个过滤条件的，相当于没有这个条件，要精确匹配，不能因为不存在而直接不过滤
//                if (!item.containsKey(entry.getKey())){
//                    log.warn("栏位：" + entry.getKey() + "不存在，请检查！");
//                    continue;
//                }

                Object value = item.get(entry.getKey());
                Object filterValue = entry.getValue();

                if (value == null){
                    if (filterValue == null){
                        continue;
                    } else if (filterValue instanceof String && "".equals(ReCommonUtils.forcetrim((String) filterValue))){
                        continue;
                    } else {
                        // 不满足条件，就会被过滤掉
                        isFilter = true;
                        break;
                    }
                }

                if (null == filterValue){
                    if ((value instanceof String) && "".equals(ReCommonUtils.forcetrim((String) value))){
                        continue;
                    } else {
                        // 不满足条件，就会被过滤掉
                        isFilter = true;
                        break;
                    }
                }

                // 注意库里面可能是有空格的，要去空才能匹配
                if (value instanceof String){
                    if (filterValue instanceof String){
                        value = ReCommonUtils.forcetrim((String) value);
                        filterValue = ReCommonUtils.forcetrim((String) filterValue);

                        if (value.equals(filterValue)){
                            continue;
                        } else {
                            // 不满足条件，就会被过滤掉
                            isFilter = true;
                            break;
                        }

                    } else {
                        // 不满足条件，就会被过滤掉
                        isFilter = true;
                        break;
                    }
                }

                // 对于数值型数据，需要做一下特殊处理
                if (value instanceof Integer){
                    if (!String.valueOf(filterValue).equals(String.valueOf(value))){
                        // 不满足条件，就会被过滤掉
                        isFilter = true;
                        break;
                    }
                }

                // 默认条件key以及value值不为空
                else if (!filterValue.equals(value)) {
                    // 不满足条件，就会被过滤掉
                    isFilter = true;
                    break;
                }
            }

            // 满足所有条件
            if (Boolean.FALSE.equals(isFilter)) {
                filterMapList.add(item);
            }
        }
        return filterMapList;
    }

    private static class CacheBean{
        public static TwoLevelLocalCache twoLevelLocalCache = (TwoLevelLocalCache) ZcCacheApplicationContextHolder.getBean("twoLevelLocalCache");
        public static LocalAndRemoteRefreshThread refreshThread = (LocalAndRemoteRefreshThread) ZcCacheApplicationContextHolder.getBean("localAndRemoteRefreshThread");
        public static ZcCacheRepository zcCacheRepository = (ZcCacheRepository) ZcCacheApplicationContextHolder.getBean("zcCacheRepository");
    }
}